home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
FM Towns: Free Software Collection 4
/
FM Towns Free Software Collection 4 - Disc 1.iso
/
pao
/
towns
/
paolib
/
cdp
/
cdp.c
next >
Wrap
Text File
|
1991-10-18
|
19KB
|
643 lines
/* << High C V1.4 >> **********************************************************
**
** CD簡易演奏ライブラリ
**
** 1991.02.09 : CREATE
** 1991.02.13 : FINISH
**
** < HISTORY >
** 1991.02.09 : CREATE
** 1991.02.19 : SHUFFLE機能の追加.
** 1991.05.30 : 清書
**
** < note > : TABS = 4
**
** Programmed by Y.Hirata ( Nifty ID : NAB03321 )
**
******************************************************************************/
pragma Off (Floating_point) ;
#define _CDP_LIB
#include <cdr.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "cdp.h"
char *COPYRIGHT = "CDP LIBRARY v0.50 1991.05.30 Programmed by Y.Hirata 1991. " ;
static char CDP_FLG_init = CDP_FALSE ; /* 初期化処理をしたか? */
static char CDP_FLG_tocread = CDP_FALSE ; /* TOC情報を取得しているか? */
static char CDP_FLG_pause = CDP_FALSE ; /* 一時停止中か? */
static char CDP_FLG_change = CDP_FALSE ; /* CDの入れ換えがあったか? */
static char CDP_FLG_shuffle = CDP_FALSE ; /* シャッフルの指定があったか? */
static char Shuffle[CDP_MAX_TRACK] ; /* シャッフル用演奏曲番号格納 */
static char Shuffle_cnt ; /* シャッフル用何曲演奏したか */
/****************************** 各種情報初期化 *****************************/
void CDP_init( void )
/*=============================================================================
** 演奏情報を初期化する.
**
** < INPUT > : なし
** < OUTPUT > : なし
** < RETURN > : なし
**
** 当ライブラリ内では必ず最初にこの関数をCALLして下さい.
=============================================================================*/
{
static char valflg = CDP_FALSE ;
if ( !valflg ) {
CDP_RANDINIT ; /* 乱数初期化 */
CDP_INFO_buf.drv = 0 ; /* FMTOWNS CDドライブ番号 */
CDP_REP_cnt = CDP_MIN_REPEAT ; /* リピート回数 */
CDP_NOW_start = CDP_MIN_TRACK ;
CDP_NOW_end = CDP_MAX_TRACK ;
valflg = CDP_TRUE ;
}
CDP_NOW_status = CDP_STAT_NOTREADY ;
CDP_NOW_musicno = CDP_ZERO ;
CDP_FLG_tocread = CDP_FALSE ;
CDP_FLG_change = CDP_FALSE ;
CDP_FLG_pause = CDP_FALSE ;
CDP_FLG_pauseplay = CDP_FALSE ;
CDP_FLG_shuffleinit = CDP_TRUE ;
CDP_FLG_init = CDP_TRUE ;
}
/****************************** CD情報の取得 *****************************/
int CDP_cdinfo( void )
/*=============================================================================
** CD情報取得命令を発行する.
**
** < INPUT > : なし
** < OUTPUT > : なし
** < RETURN > : エラー値
**
** この関数にてCD情報を取得する際には、必ず数回のリトライを行って下さい.
=============================================================================*/
{
if ( !CDP_FLG_init ) CDP_init() ;
return(
cdr_cdinfo(
CDP_INFO_buf.drv,&CDP_INFO_buf.type,
&CDP_INFO_buf.start,&CDP_INFO_buf.end,
(char *)CDP_INFO_buf.track,(char *)&CDP_INFO_buf.discend
)
) ;
}
/**************************** TOC情報の取得 *****************************/
int CDP_tocread( void )
/*=============================================================================
** TOC情報を取得する.
**
** < INPUT > : なし
** < OUTPUT > : なし
** < RETURN > : = 偽 - TOC 読み込み成功(エラーなし)
** 真 - TOC 読み込み失敗(エラーあり)
=============================================================================*/
{
int errcnt, ret ;
/*
** 共通フラグの初期化
*/
CDP_init() ;
CDP_NOW_start = CDP_MIN_TRACK ;
CDP_NOW_end = CDP_MAX_TRACK ;
/*
** TOC 読み込み
*/
errcnt = CDP_ZERO ;
do {
ret = CDP_cdinfo() ;
cdr_pause( CDP_INFO_buf.drv ) ;
errcnt++ ;
} while ( ret && errcnt<=CDP_RETRY ) ;
if ( errcnt > CDP_RETRY ) { /* TOC 読み込み失敗! */
return( CDP_ERR_NOTREADY ) ;
} else { /* TOC 読み込み成功♪ */
CDP_FLG_tocread = CDP_TRUE ;
CDP_NOW_status = CDP_STAT_STOP ;
CDP_timecalc() ;
return( CDP_ERR_NOERROR ) ;
}
}
/******************************** CD演奏 *********************************/
int CDP_mtrplay( void )
/*=============================================================================
** CD演奏命令を発行する.
**
** < INPUT > : なし
** < OUTPUT > : なし
** < RETURN > : エラー値
**
** CDP_CLOCK_start および CDP_CLOCK_end を設定してからこの関数をCALLする
** こと.
=============================================================================*/
{
if ( !CDP_FLG_init ) CDP_init() ;
if ( CDP_REP_cnt < CDP_MIN_REPEAT || CDP_REP_cnt > CDP_MAX_REPEAT )
return( CDP_ERR_PARAMETER ) ;
return(
cdr_mtrplay(
CDP_INFO_buf.drv,
(char *)&CDP_CLOCK_start,(char *)&CDP_CLOCK_end,
CDP_REP_cnt
)
) ;
}
/*************************** CD演奏状態の取得 ****************************/
int CDP_mphase( void )
/*=============================================================================
** CD演奏状態取得命令を発行する.
**
** < INPUT > : なし
** < OUTPUT > : なし
** < RETURN > : エラー値
=============================================================================*/
{
if ( !CDP_FLG_init ) CDP_init() ;
return(
cdr_mphase(
CDP_INFO_buf.drv,&CDP_NOW_status,&CDP_NOW_musicno,
(char *)&CDP_CLOCK_nowtrack,(char *)&CDP_CLOCK_nowdisc
)
) ;
}
/************************** CDの現在の状態を取得 *************************/
int CDP_status( void )
/*=============================================================================
** 演奏状態の取得とチェックを行う.
**
** < INPUT > : なし
** < OUTPUT > : なし
** < RETURN > : エラー値
**
** この関数を続けてCALLする場合には、100ms以上待ち時間をおいて下さい.
** (この関数に限ったことではないのだが・・・・・)
** たてつづけにCALLすると、演奏中の場合には、音飛びなどの原因となります.
** 何故なんだろう?困ったもんだ・・・
**
** この関数は、毎秒2~3回CALLするようにして下さい. そうしないと、演奏モード
** のとおりに演奏されません. また、演奏時間も保証されません.
=============================================================================*/
{
int ret ;
int status ; /* 現在のCD演奏状態 */
int musicno ; /* 現在演奏中の曲番号 */
CDP_TRACK nowdisc ; /* 演奏中のディスク内演奏時間 */
CDP_TRACK nowtrack ; /* 演奏中のトラック内演奏時間 */
if ( !CDP_FLG_init ) CDP_init() ;
CDP_FLG_change = CDP_FALSE ;
status = CDP_NOW_status ;
musicno = CDP_NOW_musicno ;
memcpy( (char *)&nowdisc,(char *)&CDP_CLOCK_nowdisc,
sizeof( CDP_TRACK ) ) ;
memcpy( (char *)&nowtrack,(char *)&CDP_CLOCK_nowtrack,
sizeof( CDP_TRACK ) ) ;
ret = CDP_mphase() ;
if ( ret == CDP_ERR_CHANGE ) { /* CD が入れ換えられた */
CDP_FLG_change = CDP_TRUE ;
CDP_FLG_tocread = CDP_FALSE ;
ret = CDP_mphase() ;
}
if ( !ret ) {
if ( CDP_NOW_status ) { /* 演奏中 */
CDP_NOW_status = CDP_STAT_PLAY ;
CDP_remaintime() ; /* 残り時間取得 */
} else { /* 停止中 or PAUSE中 */
if ( CDP_FLG_pause ) { /* 一時停止中 */
CDP_NOW_status = CDP_STAT_PAUSE ;
CDP_NOW_musicno = musicno ;
memcpy( (char *)&CDP_CLOCK_nowdisc,(char *)&nowdisc,
sizeof( CDP_TRACK ) ) ;
memcpy( (char *)&CDP_CLOCK_nowtrack,(char *)&nowtrack,
sizeof( CDP_TRACK ) ) ;
} else { /* 停止中 */
CDP_NOW_status = CDP_STAT_STOP ;
CDP_NOW_musicno = CDP_ZERO ;
CDP_CLOCK_nowdisc.min = CDP_ZERO ;
CDP_CLOCK_nowdisc.sec = CDP_ZERO ;
CDP_CLOCK_nowdisc.frame = CDP_ZERO ;
CDP_CLOCK_nowtrack.min = CDP_ZERO ;
CDP_CLOCK_nowtrack.sec = CDP_ZERO ;
CDP_CLOCK_nowtrack.frame = CDP_ZERO ;
/*
** 残り時間
*/
CDP_remaintime() ;
}
}
if ( CDP_FLG_change ) return( CDP_ERR_CHANGE ) ;
return( CDP_ERR_NOERROR ) ;
} else {
CDP_NOW_status = CDP_STAT_NOTREADY ;
return( ret ) ;
}
}
/**************************** 時間指定演奏処理 *****************************/
int CDP_timeplay( void )
/*=============================================================================
** 指定された時間の範囲内を演奏する.
**
** < INPUT > : なし
** < OUTPUT > : なし
** < RETURN > : エラー値
**
** CDP_CLOCK_start および CDP_CLOCK_end を設定してからこの関数をCALLする
** こと.
=============================================================================*/
{
int errcnt ;
if ( !CDP_FLG_init ) CDP_init() ;
if ( CDP_FLG_pause && !CDP_FLG_pauseplay ) return( CDP_ERR_NOWPAUSE ) ;
if ( !CDP_FLG_tocread ) return( CDP_ERR_NOTREADY ) ;
errcnt = 0 ;
do {
if ( cdr_pause( CDP_INFO_buf.drv ) == CDP_ERR_CHANGE ) {
CDP_FLG_change = CDP_TRUE ;
CDP_FLG_tocread = CDP_FALSE ;
return( CDP_ERR_CHANGE ) ;
}
if ( CDP_mtrplay() == CDP_ERR_PARAMETER ) { /* 演奏開始 */
return( CDP_ERR_PARAMETER ) ;
}
if ( CDP_mphase() ) CDP_NOW_status = CDP_STAT_NOTREADY ;
if ( ++errcnt >= CDP_RETRY ) {
return( CDP_ERR_NOTREADY ) ;
}
} while( CDP_NOW_status != CDP_STAT_PLAY ) ;
return( CDP_status() ) ;
}
/**************************** CDの演奏をします ***************************/
int CDP_play( void )
/*=============================================================================
** 指定された曲を演奏する.
**
** < INPUT > : なし
** < OUTPUT > : なし
** < RETURN > : エラー値
**
** CDP_NOW_start および CDP_NOW_end を設定してからこの関数をCALLすること.
**
** ここでは、演奏開始曲と演奏終了曲に従って演奏処理をするので、演奏中に演奏
** させない時などは、この関数を呼ぶ側で制御します.
**
** 時間指定による演奏などは、この関数を使用しないで、演奏開始/終了時間を設
** 定後 CDP_timeplay() を CALL して下さい.
=============================================================================*/
{
if ( !CDP_FLG_init ) CDP_init() ;
/*
** TOC 読み込み
*/
if ( !CDP_FLG_tocread ) {
if( CDP_tocread() ) return( CDP_ERR_NOTREADY ) ;
}
/*
** CDDA のないコンパクトディスクには用がない!
*/
if ( CDP_INFO_buf.type != CDP_TYPE_CDDA &&
CDP_INFO_buf.type != CDP_TYPE_BOTH ) return( CDP_ERR_NOMUSIC ) ;
/*
** 演奏曲番号誤り
*/
if ( CDP_NOW_start < CDP_MIN_TRACK ) return( CDP_ERR_PARAMETER ) ;
if ( CDP_NOW_end > CDP_MAX_TRACK ) return( CDP_ERR_PARAMETER ) ;
if ( CDP_NOW_start > CDP_NOW_end ) return( CDP_ERR_PARAMETER ) ;
if ( CDP_NOW_start > CDP_INFO_buf.end ||
CDP_NOW_end < CDP_INFO_buf.start )
return( CDP_ERR_PARAMETER ) ;
/*
** 演奏時間設定
*/
CDP_set_time_start( CDP_NOW_start ) ; /* 演奏開始曲データ設定 */
CDP_set_time_end( CDP_NOW_end ) ; /* 演奏終了曲データ設定 */
/*
** 演奏開始
*/
return( CDP_timeplay() ) ;
}
/************************* CD PAUSE/CONTINUE 処理 **************************/
int CDP_pause( void )
/*=============================================================================
** 一時停止のON/OFFを行う.
**
** < INPUT > : なし
** < OUTPUT > : なし
** < RETURN > : エラー値
**
** CDP_FLG_pause をこの関数以外で操作しないこと.
** また、当ライブラリ以外でCDのPAUSEやSTOPをしないこと.
=============================================================================*/
{
int ret ;
ret = CDP_status() ; /* 演奏状態のチェック */
if ( ret ) return( ret ) ;
if ( CDP_NOW_status == CDP_STAT_PAUSE ) { /* PAUSE中 */
CDP_FLG_pause = CDP_FALSE ;
if ( CDP_FLG_pauseplay ) { /* 時間指定 PLAY */
ret = CDP_timeplay() ;
if ( ret == CDP_ERR_CHANGE ) { /* CD入れ換え時 */
CDP_FLG_change = CDP_TRUE ;
CDP_FLG_tocread = CDP_FALSE ;
return( CDP_ERR_CHANGE ) ;
} else if ( ret == CDP_ERR_PARAMETER ) { /* パラメタエラー */
return( CDP_ERR_PARAMETER ) ;
}
} else { /* CONTINUE */
if ( cdr_continue( CDP_INFO_buf.drv ) == CDP_ERR_CHANGE ) {
CDP_FLG_change = CDP_TRUE ;
CDP_FLG_tocread = CDP_FALSE ;
return( CDP_ERR_CHANGE ) ;
}
}
} else if ( CDP_NOW_status == CDP_STAT_PLAY ) { /* 演奏中 */
ret = CDP_status() ;
CDP_FLG_pause = CDP_TRUE ;
CDP_FLG_pauseplay = CDP_FALSE ;
if ( ret ) return( ret ) ;
CDP_NOW_pause = CDP_NOW_musicno ;
CDP_NOW_start = CDP_NOW_musicno ;
memcpy( (char *)&CDP_CLOCK_pause,(char *)&CDP_CLOCK_nowtrack,
sizeof( CDP_TRACK ) ) ;
memcpy( (char *)&CDP_CLOCK_pausedisc,(char *)&CDP_CLOCK_nowdisc,
sizeof( CDP_TRACK ) ) ;
ret = cdr_pause( CDP_INFO_buf.drv ) ;
if ( ret ) return( ret ) ;
} else { /* 停止中 or NOT READY */
CDP_FLG_pause = CDP_FALSE ;
CDP_FLG_pauseplay = CDP_FALSE ;
}
return( CDP_status() ) ;
}
/**************************** CDの停止をします ***************************/
void CDP_stop( void )
/*=============================================================================
** CD演奏停止命令を発行する.
**
** < INPUT > : なし
** < OUTPUT > : なし
** < RETURN > : なし
=============================================================================*/
{
int errcnt, ret ;
if ( !CDP_FLG_init ) CDP_init() ;
errcnt = CDP_ZERO ;
do {
ret = cdr_mstop( CDP_INFO_buf.drv ) ;
errcnt++ ;
} while ( ret && errcnt<=CDP_RETRY ) ;
/*
** 制御フラグクリア
*/
CDP_NOW_status = CDP_STAT_STOP ;
CDP_NOW_musicno = CDP_ZERO ;
CDP_FLG_pause = CDP_FALSE ;
CDP_FLG_pauseplay = CDP_FALSE ;
}
/****************************** シャッフルの初期化 *******************************/
void CDP_shuffle_init( void )
/*=============================================================================
** シャッフルのための初期化を行う.
**
** < INPUT > : なし
** < OUTPUT > : なし
** < RETURN > : なし
**
** 乱数の初期化は、ライブラリの初期設定で行っておく.
=============================================================================*/
{
int c, cc ; /* ループカウンタ */
int music ; /* 乱数取得曲番号 */
int cnt ; /* 曲番号取得用(何番目か) */
char flg[CDP_MAX_TRACK] ; /* 乱数取得曲番号用フラグ */
CDP_FLG_shuffleinit = CDP_FALSE ; /* シャッフル初期化フラグクリア */
for ( c=0; c<CDP_INFO_buf.end; c++ ) { /* フラグ初期化 */
flg[c] = CDP_FALSE ;
}
for ( c=CDP_INFO_buf.end; c>0; c-- ) {
music = CDP_RANDOM( c ) + 1 ;
cnt = 0 ;
for ( cc=0; cc<CDP_INFO_buf.end; cc++ ) {
if ( !flg[cc] ) cnt ++ ;
if ( cnt == music ) {
flg[cc] = CDP_TRUE ;
music = cc + 1 ;
break ;
}
}
Shuffle[CDP_INFO_buf.end-c] = music ; /* 曲番号格納 */
}
Shuffle_cnt = CDP_ZERO ; /* 曲番号カウンタクリア */
}
/*************************** シャッフルの曲番号を返す ****************************/
int CDP_shuffle( void )
/*=============================================================================
** シャッフルのための曲番号を取得する.
**
** < INPUT > : なし
** < OUTPUT > : 次の演奏曲番号, 終了時は 偽値.
** < RETURN > : エラー値
**
** この関数を最初に呼ぶ時には、必ず初期化フラグ(CDP_FLG_shuffleinit)を真値に
** しておくこと.
=============================================================================*/
{
int c ;
int res ;
if ( !CDP_FLG_init ) CDP_init() ;
if ( !CDP_FLG_tocread ) {
if ( CDP_tocread() ) return( CDP_FALSE ) ;
}
if ( CDP_FLG_shuffleinit ) /* シャッフル情報初期化 */
CDP_shuffle_init() ;
if ( Shuffle_cnt > CDP_INFO_buf.end ) /* 全ての曲を終了した */
return( CDP_FALSE ) ;
res = CDP_INFO_buf.end - Shuffle_cnt ;
for ( c=0; c<res; c++ ) {
Shuffle_cnt ++ ;
if ( !CDP_data_check(Shuffle[Shuffle_cnt-1]) ) {/* 音楽ならば、 */
return( Shuffle[Shuffle_cnt-1] ) ; /* 演奏曲番号を返す */
}
}
return( CDP_FALSE ) ; /* 全ての曲を終了した */
}
/*************************** シャッフル時の状態を返す ****************************/
int CDP_shuffletime( void )
/*=============================================================================
** シャッフル演奏時の演奏時間を取得する.
**
** < INPUT > : なし
** < OUTPUT > : なし
** < RETURN > : エラー値
=============================================================================*/
{
CDP_TRACK remain ;
int ret ;
int c ;
int res ;
ret = CDP_status() ;
if ( CDP_NOW_status != CDP_STAT_PLAY &&
CDP_NOW_status != CDP_STAT_PAUSE ) {
return( ret ) ;
}
if ( CDP_FLG_shuffleinit ) { /* シャッフル情報初期化時 */
return( ret ) ;
}
/*
** 現在の曲の残り時間
*/
CDP_addtime( 0,0,0,
CDP_TIME_nowtrack.min,
CDP_TIME_nowtrack.sec,
CDP_TIME_nowtrack.frame,
&remain.min,&remain.sec,&remain.frame ) ;
/*
** シャッフルの残りの合計時間
*/
res = CDP_INFO_buf.end - Shuffle_cnt ;
for ( c=0; c<res; c++ ) {
if ( !CDP_data_check(Shuffle[Shuffle_cnt+c]) ) {/* 音楽ならば、 */
CDP_addtime( remain.min,remain.sec,remain.frame,
CDP_TIME_track[Shuffle[Shuffle_cnt+c]-1].min,
CDP_TIME_track[Shuffle[Shuffle_cnt+c]-1].sec,
CDP_TIME_track[Shuffle[Shuffle_cnt+c]-1].frame,
&remain.min,&remain.sec,&remain.frame ) ;
}
}
/*
** トータル残り時間
*/
memcpy( (char *)&CDP_TIME_nowdisc,(char *)&remain,
sizeof( CDP_TRACK ) ) ;
/*
** トータル経過時間
*/
CDP_subtime( CDP_TIME_music.min,
CDP_TIME_music.sec,
CDP_TIME_music.frame,
remain.min,remain.sec,remain.frame,
&CDP_CLOCK_nowdisc.min,
&CDP_CLOCK_nowdisc.sec,
&CDP_CLOCK_nowdisc.frame ) ;
return( ret ) ;
}
/*===========================================================================*/
#undef _CDP_LIB
/*===========================================================================*/
/******************************* デバッグ用 ********************************/
void CDP_debug_dispmsg( int errno )
/*=============================================================================
** デバッグ用にメッセージIDに対応したメッセージを出力する.
**
** < INPUT > : エラー値
** < OUTPUT > : なし
** < RETURN > : なし
=============================================================================*/
{
char *CDP_ERR_msg[] = {
"正常終了.", /* 000 */
"CDがセットされていません.", /* 001 */
"パラメタに誤りがあります.", /* 002 */
"CDドライブが接続されていません.", /* 004 */
"コマンドが異常終了しました.", /* 008 */
"メディアエラー.", /* 016 */
"ハードエラー.", /* 032 */
"パリティエラー.", /* 064 */
"メディアが交換されてます.", /* 128 */
"デバイス番号に誤りがあります.", /* 256 */
"セクタ長が違います.", /* 257 */
"音楽演奏中です.", /* 258 */
"一時停止中です.", /* 260 */
"一時停止状態ではありません.", /* 264 */
"音楽データがありません.", /* 272 */
"該当メッセージなし." /* 003 */
} ;
char *CDP_STATUS_msg[] = {
"CDがセットされていません.",
"停止中です.",
"演奏中です.",
"一時停止中です."
} ;
int c, chk, no ;
int nomsg = 15 ;
chk = 0x0001 ;
no = 0 ;
for ( c=0; c<8; c++ ) {
if ( ((errno & 0x00ff) & chk) == chk ) no = c + 1 ;
chk <<= 1 ;
}
if ( errno > 255 ) no += 9 ;
if ( errno != 0 && no == 0 ) no = nomsg ;
if ( no < 0 || no > nomsg ) no = nomsg ;
printf( "CDP DEBUG MSG (%04xh) : %s\n",errno,CDP_ERR_msg[no] ) ;
no = CDP_NOW_status ;
if ( no < 0 ) {
no = 0 ;
} else {
no ++ ;
}
printf( "Now status (%d) : %s\n",CDP_NOW_status,CDP_STATUS_msg[no] ) ;
}